package basic.chapter4;

/**
 * @author Kevin
 * @date 2020/2/20 20:14
 *保护无关联事务：余额、账户密码；使用细粒度锁
 * 当然，我们也可以用一把互斥锁来保护多个资源，例如我们可以用 this 这一把锁来管理账户类里所有的资源：账户余额和用户密码。具体实现很简单，示例程序中所有的方法都增加同步关键字 synchronized 就可以了
 * 但是用一把锁有个问题，就是性能太差，会导致取款、查看余额、修改密码、查看密码这四个操作都是串行的。而我们用两把锁，取款和修改密码是可以并行的。
 * 锁要使用不可变对象，不能使用可变对象
 */
public class Account {
    //锁：保护账户余额
    public final Object balLock = new Object();
    //账户余额
    public Integer balance;
    //锁：保护账户密码
    public final Object pwLock = new Object();
    //账户密码
    public String password;

    //取款
    void withdraw(Integer amt) {
        synchronized(balLock) {
            if (this.balance >= amt) {
                this.balance -= amt;
            }
        }
    }
    //查看余额
    Integer getBalance() {
        synchronized(balLock) {
            return balance;
        }
    }

    //更改密码
    void updatePassword(String pw) {
        synchronized (pwLock) {
            this.password = pw;
        }
    }
    // 查看密码
    String getPassword() {
        synchronized(pwLock) {
            return this.password;
        }
    }
    /**
     * 保护有关联关系的多个资源
     * 例如银行业务里面的转账操作，账户 A 减少 100 元，账户 B 增加 100 元。这两个账户就是有关联关系的
     */
    //错误示范
    //问题就出在 this 这把锁上，this 这把锁可以保护自己的余额 this.balance，却保护不了别人的余额 target.balance，就像你不能用自家的锁来保护别人家的资产，也不能用自己的票来保护别人的座位一样。
    synchronized void transfer(Account target, int amt) {
        if (this.balance > amt) {
            this.balance -= amt;
            target.balance += amt;
        }
    }
    //正确示范：多个对象（资源）共用一把锁，见Account1


}
